/**
 * Created by Void on 2017/9/18.
 */

import {
    AfterViewInit, Component, ElementRef, Input, OnInit, OnDestroy, Renderer2,
    ViewChild, AfterContentInit, Output, EventEmitter, ViewEncapsulation, forwardRef, Optional
} from '@angular/core';
import {
    NavController, RootNode, NavControllerBase, ViewController, App, DeepLinker,
    DomController, Platform
} from 'ionic-angular';
import { NavigationContainer } from 'ionic-angular/navigation/navigation-container';
import { Observable } from 'rxjs/Observable';
import {Subscription} from 'rxjs/Subscription';

import {SuperTab} from './super-tab';
import {SuperTabsToolbar} from "./super-tabs-toolbar";
// import {SuperTabsController} from "./super-tabs-controller";
import {SuperTabsContainer} from "./super-tabs-container";
import {DIRECTION_SWITCH} from "ionic-angular/umd/navigation/nav-util";
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/debounceTime';

export interface SuperTabsConfig {
    maxDragAngle?:number;
    dragThreshold?:number; // 拖动的临界值
    transitionEase?:string; // 动画的方式
    transitionDuration?:number; // 滑动页面切换的动画时长
    sideMenu?:'left'|'right'|'both';
    sideMenuThreshold?:number;
    shortSwipeDuration?:number;
}
@Component({
    selector: 'super-tabs',
    template: `
<super-tabs-toolbar [config]="config"
[color]="color" [badgeColor]="badgeColor"
[scrollTabNum]="scrollTabNum"
[selectedTab]="selectedTabIndex"
(tabSelect)="onToolbarTabSelect($event)">
</super-tabs-toolbar>
<super-tabs-container [config]="config" [tabsCount]="_tabs.length" [selectedTabIndex]="selectedTabIndex" (ondrag)="onDrag($event)">
<ng-content></ng-content>
</super-tabs-container>
`,
    encapsulation: ViewEncapsulation.None,
    providers: [
        {
            provide: RootNode,
            useExisting: forwardRef(() => SuperTabs)
        }
    ]

})
export class SuperTabs implements OnInit,AfterContentInit,AfterViewInit,OnDestroy,RootNode,NavigationContainer {

    @Input() badgeColor:string = 'danger';
    @Input() id:string;
    @Input() color:string = 'primary';
    @Input() scrollTabNum:number = 3;
    @Input() config:SuperTabsConfig;
    @Input() selectedTabIndex:number = 0;
    // set selectedTabIndex(val:number) {
    //     this._selectedTabIndex = Number(val);
    //     // this.init && this.alignIndicatorPosition(true);
    // }
    // get selectedTabIndex():number {
    //     return this._selectedTabIndex;
    // }

    // @Input()
    // set scrollTabNum(val:number) {
    //     this._scrollTabs = typeof val !== 'boolean' || val === true;
    // }
    // get scrollTabNum():boolean {
    //     return this._scrollTabs;
    // }
    @Output() tabSelect:EventEmitter<any> = new EventEmitter<any>();

    @Input() name:string;

    /**
     * hieght of tabs
     */
    @Input()
    set height(val:number) {
        this.rnd.setStyle(this.el.nativeElement, 'height', val + 'px');
    }

    get height():number {
        return this.el.nativeElement.offsetHeight;
    }


    private _isToolbarVisible:boolean = true;
    private _tabs:SuperTab[] = [];
    private _selectedTabIndex:number = 0;
    private _scrollTabs:boolean = false;

    @ViewChild(SuperTabsToolbar) private toolbar:SuperTabsToolbar;
    @ViewChild(SuperTabsContainer) private tabsContainer:SuperTabsContainer;

    private maxIndicatorPosition:number;
    private hasIcons:boolean = false;
    private hasTitles:boolean = false;
    private init:boolean = false;

    parent:NavControllerBase;

    private watches:Subscription[] = [];

    constructor(
        @Optional() parent:NavController,   // @Optional 当Angular找不到依赖时，@Optional装饰器会告诉Angular继续执行，Angualr会把此注入参数设置为null（而不是默认的抛出错误的行为）。
        @Optional() public viewCtrl: ViewController,
        private rnd:Renderer2,
        private el:ElementRef,
        // private superTabsCtrl:SuperTabsController,
        private domCtrl:DomController,
        private _app: App,
        private _plt:Platform,
        private linker:DeepLinker
    ) {
        /***
         * 获取导航控制器 强制转成 导航基础控制器
         * 初始化时 要将本组件 注册为 导航控制器的子控制器(猜测：push的时候 也会进行新控制器的注册)
         */
        this.parent = <NavControllerBase>parent;

        if (this.parent) {
            this.parent.registerChildNav(this);

        } else if(viewCtrl && viewCtrl.getNav()) {
            this.parent = <any>viewCtrl.getNav();
            this.parent.registerChildNav(this);

        } else if (this._app) {
            this._app.registerRootNav(this);
        }

        const obsToMerge: Observable<any>[] = [
            Observable.fromEvent(window, 'orientationchange'),
            Observable.fromEvent(window, 'resize')
        ];

        if (viewCtrl) {
            obsToMerge.push(viewCtrl.didEnter);
            viewCtrl._setContent(this);
            viewCtrl._setContentRef(el);
        }

        // re-adjust the height of the slider when the orientation changes
        const $windowResize = Observable.merge.apply(this, obsToMerge).debounceTime(10);

        const windowResizeSub = $windowResize.subscribe(() => {
            this.setMaxIndicatorPosition();
            this.updateTabWidth();
            this.setFixedIndicatorWidth();
            this.refreshTabWidths();
            // this.tabsContainer.refreshDimensions();
            // this.tabsContainer.slideTo(this.selectedTabIndex);
            this.alignIndicatorPosition();
            this.refreshContainerHeight();
        });

        this.watches.push(windowResizeSub);
    }

    ngOnInit() {

        // 设置tabsconfig
        const defaultConfig:SuperTabsConfig = {
            dragThreshold: 10,
            maxDragAngle: 40,
            sideMenuThreshold: 50,
            transitionDuration: 300,
            transitionEase: 'cubic-bezier(0.35, 0, 0.25, 1)',
            shortSwipeDuration: 300
        };
        this.config = Object.assign({}, defaultConfig, this.config);

        // 设置tabs 的 id
        this.id = this.id || `super-tabs-${++superTabsIds}`;

        // 向tabsController中注册 当前的superTabs
        // this.superTabsCtrl.registerInstance(this);
    }

    ngAfterContentInit() {
        this.updateTabWidth();
        this.toolbar.tabs = this._tabs;
        this._scrollTabs = this._tabs.length > this.scrollTabNum;
        console.log(this._scrollTabs);
    }

    ngAfterViewInit() {

        const tabsSegment = this.linker.getSegmentByNavIdOrName(this.id, this.name);

        if (tabsSegment) {
            this.selectedTabIndex = this.getTabIndexById(tabsSegment.id);
        }

        // this.linker.navChange(DIRECTION_SWITCH);

        if (!this.hasTitles) this._isToolbarVisible = false;

        // this.tabsContainer.slideTo(this.selectedTabIndex, false);
        this.refreshTabStates();

        this.setFixedIndicatorWidth();

        // we need this to make sure the "slide" thingy doesn't move outside the screen
        this.setMaxIndicatorPosition();

        setTimeout(() => this.alignIndicatorPosition(), 100);

        this.refreshContainerHeight();

        this.init = true;

    }

    ngOnDestroy(){
        // 取消订阅
        this.watches.forEach((watch:Subscription) => {
            watch.unsubscribe();
        });

        // 取消 导航子控制器的注册
        this.parent.unregisterChildNav(this);

        // this.superTabsCtrl.unregisterInstance(this.id);
    }

    onToolbarTabSelect(index:number) {
        // 下面视图的切换
        this.tabsContainer.slideTo(index);
        // tabs 的切换
        this.onTabChange(index);

        this.alignIndicatorPosition(true);
    }

    onTabChange(index:number) {
        if (index === this.selectedTabIndex) {
            this.tabSelect.emit({
                index,
                id: this._tabs[index].tabId,
                changed: false
            });
        }

        if (index <= this._tabs.length) {
            const currentTab:SuperTab = this.getActiveTab();
            let activeView:ViewController = currentTab.getActive();

            // 未切换视图之前 的 活动视图
            if (activeView) {
                activeView._willLeave(false);
                activeView._didLeave();
            }

            this.selectedTabIndex = index;

            // nav切换
            // this.linker.navChange(DIRECTION_SWITCH);

            this.refreshTabStates();

            // 切换视图后 的 活动视图
            activeView = this.getActiveTab().getActive();
            if (activeView){
                activeView._willEnter();
                activeView._didEnter();
            }

            this.tabSelect.emit({
                index,
                id: this._tabs[index].tabId,
                changed: true
            });
        }
    }

    getActiveTab():SuperTab {
        return this._tabs[this.selectedTabIndex];
    }
    getTabIndexById(tabId: string): number {
        return this._tabs.findIndex((tab: SuperTab) => tab.tabId === tabId);
    }

    getTabById(tabId: string): SuperTab {
        return this._tabs.find((tab: SuperTab) => tab.tabId === tabId);
    }

    getActiveChildNavs(): NavigationContainer[] {
        return [this._tabs[this.selectedTabIndex]];
    }

    // RootNode  代理
    getElementRef() { return this.el; }
    initPane() { return true; }
    paneChanged() {}
    getSelected() {}
    setTabbarPosition() {}

    // NavigationContainer  代理
    getType(): string { return; }
    getSecondaryIdentifier(): string { return; }
    getAllChildNavs(): any[] {
        return this._tabs;
    }

    indexSegmentButtonWidths() {
        this._plt.raf(() => this.toolbar.indexSegmentButtonWidths());
    }

    onContainerTabSelect(ev: {index: number; changed: boolean}) {
        if (ev.changed) {
            this.onTabChange(ev.index);
        }
        this.alignIndicatorPosition(true);
    }

    // 添加tab
    addTab(tab:SuperTab):void{
        tab.rootParams = tab.rootParams || {};
        tab.rootParams.rootNavCtrl = this.parent;

        // 给每一个tab 设置ID  规则  super-tabs-tabsID-tab-index
        tab.tabId = tab.tabId || `super-tabs-${this.id}-tab-${this._tabs.length}}`;

        this._tabs.push(tab);

        if (tab.title){
            this.hasTitles = true;
        }
        // 设置tab的宽度
        tab.setWidth(this.el.nativeElement.offsetWidth);

    }

    // 监听拖动事件
    // onDrag(){
    //     if (!this._isToolbarVisible) return;
    //
    //     this.domCtrl.write( () => {
    //         const singleSlideWidth = this.tabsContainer.tabWidth;
    //         const slidesWidth = this.tabsContainer.containerWidth;
    //
    //         let percentage = Math.abs(this.tabsContainer.containerPosition / slidesWidth);
    //
    //         if (this.scrollTabs){
    //             const originalSlideStart = singleSlideWidth * this.selectedTabIndex;
    //             const originalPosition = this.getRelativeIndicatorPosition();
    //             const originalWidth = this.getSegmentButtonWidth(); // 获取具体tab-button 的 宽度. 因为每一个buttn的宽度不一样
    //
    //             let nextPosition:number,nextWidth:number,indicatorPosition:number,indicatorWidth:number;
    //
    //             const deltaTabPos = originalSlideStart - Math.abs(this.tabsContainer.containerPosition);
    //
    //             percentage = Math.abs(deltaTabPos / singleSlideWidth);
    //
    //             if (deltaTabPos < 0){
    //                 // 下一个slide
    //                 nextPosition = this.getRelativeIndicatorPosition(this.selectedTabIndex + 1);
    //                 nextWidth = this.getSegmentButtonWidth(this.selectedTabIndex + 1);
    //                 indicatorPosition = originalPosition + percentage * (nextPosition - originalPosition);
    //             }else {
    //                 // 上一个slide
    //                 nextPosition = this.getRelativeIndicatorPosition(this.selectedTabIndex - 1);
    //                 nextWidth = this.getSegmentButtonWidth(this.selectedTabIndex - 1);
    //                 indicatorPosition = originalPosition - percentage * (originalPosition - nextPosition);
    //             }
    //
    //             const deltaWidth:number = nextWidth - originalWidth;
    //
    //             indicatorWidth = originalWidth + percentage * deltaWidth;
    //             if( (originalWidth > nextWidth && indicatorWidth < nextWidth) || (originalWidth < nextWidth && indicatorWidth > nextWidth)){
    //                 indicatorWidth = nextWidth;
    //             }
    //             this.alignIndicatorPosition();
    //             this.toolbar.setIndicatorProperties(indicatorWidth,indicatorPosition);
    //         }else {
    //
    //         }
    //     })
    // }

    // private alignTabButtonsContainer(animate?:boolean){
    //     const
    //         mw:number = this.el.nativeElement.offsetWidth,
    //         iw:number = this.toolbar
    // }

    private updateTabWidth() {
        this.tabsContainer.tabWidth = this.el.nativeElement.offsetWidth;
    }

    private refreshTabWidths() {
        const width: number = this.el.nativeElement.offsetWidth;
        this._tabs.forEach((tab: SuperTab) => tab.setWidth(width));
    }

    private refreshContainerHeight() {
        let heightOffset: number = 0;

        if (this._isToolbarVisible && this.hasTitles) {
            heightOffset = 40;
        }
        this.rnd.setStyle(this.tabsContainer.getNativeElement(), 'height', `calc(100% - ${heightOffset}px)`);
    }

    private alignIndicatorPosition(animate: boolean = false) {
        if (!this._isToolbarVisible) return;

        if (this._scrollTabs) {
            // this.toolbar.alignIndicator(this.getRelativeIndicatorPosition(), this.getSegmentButtonWidth(), animate);
            // this.alignTabButtonsContainer(animate);
        } else {
            this.toolbar.setIndicatorPosition(this.getAbsoluteIndicatorPosition(), animate);
        }
    }

    private setMaxIndicatorPosition() {
        if (this.el && this.el.nativeElement) {
            this.maxIndicatorPosition = this.el.nativeElement.offsetWidth - (this.el.nativeElement.offsetWidth / this._tabs.length);
        }
    }


    private getRelativeIndicatorPosition(index: number = this.selectedTabIndex): number {
        let position: number = 0;
        for (let i: number = 0; i < this.toolbar.segmentButtonWidths.length; i++) {
            if (index > Number(i)) {
                position += this.toolbar.segmentButtonWidths[i];
            }
        }
        return position;
    }

    private getAbsoluteIndicatorPosition(): number {
        let position: number = this.selectedTabIndex * this.tabsContainer.tabWidth / this._tabs.length;
        return position <= this.maxIndicatorPosition ? position : this.maxIndicatorPosition;
    }

    private setFixedIndicatorWidth() {
        // if (this._scrollTabs || !this._isToolbarVisible) return;
        // the width of the "slide", should be equal to the width of a single `ion-segment-button`
        // we'll just calculate it instead of querying for a segment button
        this.toolbar.setIndicatorWidth(false);
    }


    private getSegmentButtonWidth(index:number = this.selectedTabIndex){
        if (!this._isToolbarVisible) return ;
        return this.toolbar.segmentButtonWidths[index];
    }

    private refreshTabStates() {
        this._tabs.forEach((tab, i) => {
            tab.setActive(i === this.selectedTabIndex);
            // 预加载 前 后 两个tab
            tab.load(Math.abs(this.selectedTabIndex - i) < 2);
        });
    }
}
let superTabsIds = -1;